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.lar;
016    
017    import com.liferay.portal.kernel.exception.SystemException;
018    import com.liferay.portal.kernel.lar.DataLevel;
019    import com.liferay.portal.kernel.lar.PortletDataContext;
020    import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
021    import com.liferay.portal.kernel.lar.PortletDataHandlerChoice;
022    import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
023    import com.liferay.portal.kernel.lar.PortletDataHandlerKeys;
024    import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
025    import com.liferay.portal.kernel.log.Log;
026    import com.liferay.portal.kernel.log.LogFactoryUtil;
027    import com.liferay.portal.kernel.staging.MergeLayoutPrototypesThreadLocal;
028    import com.liferay.portal.kernel.util.GetterUtil;
029    import com.liferay.portal.kernel.util.MapUtil;
030    import com.liferay.portal.kernel.util.StringPool;
031    import com.liferay.portal.kernel.util.Validator;
032    import com.liferay.portal.kernel.workflow.WorkflowConstants;
033    import com.liferay.portal.model.Group;
034    import com.liferay.portal.model.Layout;
035    import com.liferay.portal.model.Portlet;
036    import com.liferay.portal.service.GroupLocalServiceUtil;
037    import com.liferay.portal.service.LayoutLocalServiceUtil;
038    import com.liferay.portal.service.PortletLocalServiceUtil;
039    import com.liferay.portal.util.PortalUtil;
040    import com.liferay.portal.util.PropsValues;
041    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
042    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
043    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
044    import com.liferay.portlet.journal.model.JournalArticle;
045    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
046    import com.liferay.portlet.journal.service.JournalContentSearchLocalServiceUtil;
047    import com.liferay.portlet.journal.service.permission.JournalPermission;
048    
049    import java.util.Map;
050    
051    import javax.portlet.PortletPreferences;
052    
053    /**
054     * <p>
055     * Provides the Journal Content portlet export and import functionality, which
056     * is to clone the article, structure, and template referenced in the Journal
057     * Content portlet if the article is associated with the layout's group. Upon
058     * import, a new instance of the corresponding article, structure, and template
059     * will be created or updated. The author of the newly created objects are
060     * determined by the JournalCreationStrategy class defined in
061     * <i>portal.properties</i>.
062     * </p>
063     *
064     * <p>
065     * This <code>PortletDataHandler</code> differs from from
066     * <code>JournalPortletDataHandlerImpl</code> in that it only exports articles
067     * referenced in Journal Content portlets. Articles not displayed in Journal
068     * Content portlets will not be exported unless
069     * <code>JournalPortletDataHandlerImpl</code> is activated.
070     * </p>
071     *
072     * @author Joel Kozikowski
073     * @author Raymond Aug??
074     * @author Bruno Farache
075     * @author Daniel Kocsis
076     * @see    com.liferay.portal.kernel.lar.PortletDataHandler
077     * @see    com.liferay.portlet.journal.lar.JournalCreationStrategy
078     * @see    com.liferay.portlet.journal.lar.JournalPortletDataHandler
079     */
080    public class JournalContentPortletDataHandler
081            extends JournalPortletDataHandler {
082    
083            public static final String NAMESPACE = "journal-content";
084    
085            public JournalContentPortletDataHandler() {
086                    setDataLevel(DataLevel.PORTLET_INSTANCE);
087                    setDataPortletPreferences("articleId", "ddmTemplateKey", "groupId");
088                    setExportControls(
089                            new PortletDataHandlerBoolean(
090                                    NAMESPACE, "selected-web-content", true, false,
091                                    new PortletDataHandlerControl[] {
092                                            new PortletDataHandlerChoice(
093                                                    NAMESPACE, "referenced-content-behavior", 0,
094                                                    new String[] {"include-if-modified", "include-always"})
095                                    },
096                                    JournalArticle.class.getName()));
097                    setPublishToLiveByDefault(
098                            PropsValues.JOURNAL_CONTENT_PUBLISH_TO_LIVE_BY_DEFAULT);
099            }
100    
101            @Override
102            protected PortletPreferences doDeleteData(
103                            PortletDataContext portletDataContext, String portletId,
104                            PortletPreferences portletPreferences)
105                    throws Exception {
106    
107                    if (portletPreferences == null) {
108                            return portletPreferences;
109                    }
110    
111                    portletPreferences.setValue("articleId", StringPool.BLANK);
112                    portletPreferences.setValue("ddmTemplateKey", StringPool.BLANK);
113                    portletPreferences.setValue("groupId", StringPool.BLANK);
114    
115                    return portletPreferences;
116            }
117    
118            @Override
119            protected PortletPreferences doProcessExportPortletPreferences(
120                            PortletDataContext portletDataContext, String portletId,
121                            PortletPreferences portletPreferences)
122                    throws Exception {
123    
124                    portletDataContext.addPortletPermissions(
125                            JournalPermission.RESOURCE_NAME);
126    
127                    String articleId = portletPreferences.getValue("articleId", null);
128    
129                    if (articleId == null) {
130                            if (_log.isDebugEnabled()) {
131                                    _log.debug(
132                                            "No article id found in preferences of portlet " +
133                                                    portletId);
134                            }
135    
136                            return portletPreferences;
137                    }
138    
139                    long articleGroupId = GetterUtil.getLong(
140                            portletPreferences.getValue("groupId", StringPool.BLANK));
141    
142                    if (articleGroupId <= 0) {
143                            if (_log.isWarnEnabled()) {
144                                    _log.warn(
145                                            "No group id found in preferences of portlet " + portletId);
146                            }
147    
148                            return portletPreferences;
149                    }
150    
151                    long previousScopeGroupId = portletDataContext.getScopeGroupId();
152    
153                    if (articleGroupId != previousScopeGroupId) {
154                            portletDataContext.setScopeGroupId(articleGroupId);
155                    }
156    
157                    JournalArticle article = fetchLatestArticle(articleGroupId, articleId);
158    
159                    if (article == null) {
160                            if (_log.isWarnEnabled()) {
161                                    _log.warn(
162                                            "Portlet " + portletId +
163                                                    " refers to an invalid article ID " + articleId);
164                            }
165    
166                            portletDataContext.setScopeGroupId(previousScopeGroupId);
167    
168                            return portletPreferences;
169                    }
170    
171                    if (!MapUtil.getBoolean(
172                                    portletDataContext.getParameterMap(),
173                                    PortletDataHandlerKeys.PORTLET_DATA) &&
174                            MergeLayoutPrototypesThreadLocal.isInProgress()) {
175    
176                            portletDataContext.setScopeGroupId(previousScopeGroupId);
177    
178                            return portletPreferences;
179                    }
180    
181                    if (portletDataContext.getBooleanParameter(
182                                    NAMESPACE, "selected-web-content")) {
183    
184                            StagedModelDataHandlerUtil.exportReferenceStagedModel(
185                                    portletDataContext, portletId, article);
186                    }
187                    else {
188                            Portlet referrerPortlet = PortletLocalServiceUtil.getPortletById(
189                                    portletId);
190    
191                            portletDataContext.addReferenceElement(
192                                    referrerPortlet, portletDataContext.getExportDataRootElement(),
193                                    article, PortletDataContext.REFERENCE_TYPE_DEPENDENCY, true);
194                    }
195    
196                    String defaultTemplateId = article.getTemplateId();
197                    String preferenceTemplateId = portletPreferences.getValue(
198                            "ddmTemplateKey", null);
199    
200                    if (Validator.isNotNull(defaultTemplateId) &&
201                            Validator.isNotNull(preferenceTemplateId) &&
202                            !defaultTemplateId.equals(preferenceTemplateId)) {
203    
204                            DDMTemplate ddmTemplate = DDMTemplateLocalServiceUtil.fetchTemplate(
205                                    article.getGroupId(),
206                                    PortalUtil.getClassNameId(DDMStructure.class),
207                                    preferenceTemplateId, true);
208    
209                            if (ddmTemplate == null) {
210                                    ddmTemplate = DDMTemplateLocalServiceUtil.getTemplate(
211                                            article.getGroupId(),
212                                            PortalUtil.getClassNameId(DDMStructure.class),
213                                            defaultTemplateId, true);
214    
215                                    portletPreferences.setValue(
216                                            "ddmTemplateKey", defaultTemplateId);
217                            }
218    
219                            StagedModelDataHandlerUtil.exportReferenceStagedModel(
220                                    portletDataContext, article, ddmTemplate,
221                                    PortletDataContext.REFERENCE_TYPE_STRONG);
222                    }
223    
224                    portletDataContext.setScopeGroupId(previousScopeGroupId);
225    
226                    return portletPreferences;
227            }
228    
229            @Override
230            protected PortletPreferences doProcessImportPortletPreferences(
231                            PortletDataContext portletDataContext, String portletId,
232                            PortletPreferences portletPreferences)
233                    throws Exception {
234    
235                    portletDataContext.importPortletPermissions(
236                            JournalPermission.RESOURCE_NAME);
237    
238                    long previousScopeGroupId = portletDataContext.getScopeGroupId();
239    
240                    long importGroupId = GetterUtil.getLong(
241                            portletPreferences.getValue("groupId", null));
242    
243                    if (importGroupId == portletDataContext.getSourceGroupId()) {
244                            portletDataContext.setScopeGroupId(portletDataContext.getGroupId());
245                    }
246    
247                    if (importGroupId ==
248                                    portletDataContext.getSourceCompanyGroupId()) {
249    
250                            portletDataContext.setScopeGroupId(
251                                    portletDataContext.getCompanyGroupId());
252                    }
253    
254                    StagedModelDataHandlerUtil.importReferenceStagedModels(
255                            portletDataContext, DDMStructure.class);
256    
257                    StagedModelDataHandlerUtil.importReferenceStagedModels(
258                            portletDataContext, DDMTemplate.class);
259    
260                    StagedModelDataHandlerUtil.importReferenceStagedModels(
261                            portletDataContext, JournalArticle.class);
262    
263                    String articleId = portletPreferences.getValue("articleId", null);
264    
265                    if (Validator.isNotNull(articleId)) {
266                            Map<String, String> articleIds =
267                                    (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
268                                            JournalArticle.class + ".articleId");
269    
270                            articleId = MapUtil.getString(articleIds, articleId, articleId);
271    
272                            portletPreferences.setValue("articleId", articleId);
273    
274                            String importedArticleGroupId = String.valueOf(
275                                    portletDataContext.getScopeGroupId());
276    
277                            JournalArticle article = fetchParentSiteArticle(
278                                    portletDataContext.getScopeGroupId(), articleId);
279    
280                            if (article != null) {
281                                    importedArticleGroupId = String.valueOf(article.getGroupId());
282                            }
283    
284                            portletPreferences.setValue("groupId", importedArticleGroupId);
285    
286                            Layout layout = LayoutLocalServiceUtil.getLayout(
287                                    portletDataContext.getPlid());
288    
289                            JournalContentSearchLocalServiceUtil.updateContentSearch(
290                                    layout.getGroupId(), layout.isPrivateLayout(),
291                                    layout.getLayoutId(), portletId, articleId, true);
292                    }
293                    else {
294                            portletPreferences.setValue("groupId", StringPool.BLANK);
295                            portletPreferences.setValue("articleId", StringPool.BLANK);
296                    }
297    
298                    String ddmTemplateKey = portletPreferences.getValue(
299                            "ddmTemplateKey", null);
300    
301                    if (Validator.isNotNull(ddmTemplateKey)) {
302                            Map<String, String> ddmTemplateKeys =
303                                    (Map<String, String>)portletDataContext.getNewPrimaryKeysMap(
304                                            DDMTemplate.class + ".ddmTemplateKey");
305    
306                            ddmTemplateKey = MapUtil.getString(
307                                    ddmTemplateKeys, ddmTemplateKey, ddmTemplateKey);
308    
309                            portletPreferences.setValue("ddmTemplateKey", ddmTemplateKey);
310                    }
311                    else {
312                            portletPreferences.setValue("ddmTemplateKey", StringPool.BLANK);
313                    }
314    
315                    portletDataContext.setScopeGroupId(previousScopeGroupId);
316    
317                    return portletPreferences;
318            }
319    
320            private JournalArticle fetchLatestArticle(
321                            long articleGroupId, String articleId)
322                    throws SystemException {
323    
324                    JournalArticle article =
325                            JournalArticleLocalServiceUtil.fetchLatestArticle(
326                                    articleGroupId, articleId, WorkflowConstants.STATUS_APPROVED);
327    
328                    if (article == null) {
329                            article = JournalArticleLocalServiceUtil.fetchLatestArticle(
330                                    articleGroupId, articleId, WorkflowConstants.STATUS_EXPIRED);
331                    }
332    
333                    return article;
334            }
335    
336            private JournalArticle fetchParentSiteArticle(
337                            long groupId, String articleId)
338                    throws Exception {
339    
340                    JournalArticle article = fetchLatestArticle(groupId, articleId);
341    
342                    if (article == null) {
343                            Group group = GroupLocalServiceUtil.getGroup(groupId);
344    
345                            for (Group parentGroup : group.getAncestors()) {
346                                    article = fetchParentSiteArticle(
347                                            parentGroup.getGroupId(), articleId);
348    
349                                    if (article != null) {
350                                            break;
351                                    }
352                            }
353                    }
354    
355                    return article;
356            }
357    
358            private static Log _log = LogFactoryUtil.getLog(
359                    JournalContentPortletDataHandler.class);
360    
361    }