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.journal.lar;
016    
017    import com.liferay.portal.kernel.dao.orm.ActionableDynamicQuery;
018    import com.liferay.portal.kernel.dao.orm.DynamicQuery;
019    import com.liferay.portal.kernel.dao.orm.DynamicQueryFactoryUtil;
020    import com.liferay.portal.kernel.dao.orm.ProjectionFactoryUtil;
021    import com.liferay.portal.kernel.dao.orm.Property;
022    import com.liferay.portal.kernel.dao.orm.PropertyFactoryUtil;
023    import com.liferay.portal.kernel.dao.orm.RestrictionsFactoryUtil;
024    import com.liferay.portal.kernel.exception.PortalException;
025    import com.liferay.portal.kernel.exception.SystemException;
026    import com.liferay.portal.kernel.lar.BasePortletDataHandler;
027    import com.liferay.portal.kernel.lar.ManifestSummary;
028    import com.liferay.portal.kernel.lar.PortletDataContext;
029    import com.liferay.portal.kernel.lar.PortletDataHandlerBoolean;
030    import com.liferay.portal.kernel.lar.PortletDataHandlerControl;
031    import com.liferay.portal.kernel.lar.StagedModelDataHandlerUtil;
032    import com.liferay.portal.kernel.lar.StagedModelType;
033    import com.liferay.portal.kernel.util.PortalClassLoaderUtil;
034    import com.liferay.portal.kernel.util.Validator;
035    import com.liferay.portal.kernel.xml.Element;
036    import com.liferay.portal.util.PortalUtil;
037    import com.liferay.portal.util.PropsValues;
038    import com.liferay.portlet.dynamicdatamapping.model.DDMStructure;
039    import com.liferay.portlet.dynamicdatamapping.model.DDMTemplate;
040    import com.liferay.portlet.dynamicdatamapping.service.DDMStructureLocalServiceUtil;
041    import com.liferay.portlet.dynamicdatamapping.service.DDMTemplateLocalServiceUtil;
042    import com.liferay.portlet.dynamicdatamapping.service.persistence.DDMStructureExportActionableDynamicQuery;
043    import com.liferay.portlet.dynamicdatamapping.service.persistence.DDMTemplateExportActionableDynamicQuery;
044    import com.liferay.portlet.journal.model.JournalArticle;
045    import com.liferay.portlet.journal.model.JournalFeed;
046    import com.liferay.portlet.journal.model.JournalFolder;
047    import com.liferay.portlet.journal.service.JournalArticleLocalServiceUtil;
048    import com.liferay.portlet.journal.service.JournalFolderLocalServiceUtil;
049    import com.liferay.portlet.journal.service.permission.JournalPermission;
050    import com.liferay.portlet.journal.service.persistence.JournalArticleExportActionableDynamicQuery;
051    import com.liferay.portlet.journal.service.persistence.JournalFeedExportActionableDynamicQuery;
052    import com.liferay.portlet.journal.service.persistence.JournalFolderExportActionableDynamicQuery;
053    
054    import java.util.ArrayList;
055    import java.util.List;
056    
057    import javax.portlet.PortletPreferences;
058    
059    /**
060     * <p>
061     * Provides the Journal portlet export and import functionality, which is to
062     * clone all articles, structures, and templates associated with the layout's
063     * group. Upon import, new instances of the corresponding articles, structures,
064     * and templates are created or updated according to the DATA_MIRROW strategy
065     * The author of the newly created objects are determined by the
066     * JournalCreationStrategy class defined in <i>portal.properties</i>. That
067     * strategy also allows the text of the journal article to be modified prior to
068     * import.
069     * </p>
070     *
071     * <p>
072     * This <code>PortletDataHandler</code> differs from
073     * <code>JournalContentPortletDataHandlerImpl</code> in that it exports all
074     * articles owned by the group whether or not they are actually displayed in a
075     * portlet in the layout set.
076     * </p>
077     *
078     * @author Raymond Aug??
079     * @author Joel Kozikowski
080     * @author Brian Wing Shun Chan
081     * @author Bruno Farache
082     * @author Karthik Sudarshan
083     * @author Wesley Gong
084     * @author Hugo Huijser
085     * @author Daniel Kocsis
086     * @see    com.liferay.portal.kernel.lar.PortletDataHandler
087     * @see    com.liferay.portlet.journal.lar.JournalContentPortletDataHandler
088     * @see    com.liferay.portlet.journal.lar.JournalCreationStrategy
089     */
090    public class JournalPortletDataHandler extends BasePortletDataHandler {
091    
092            public static final String NAMESPACE = "journal";
093    
094            public JournalPortletDataHandler() {
095                    setDataLocalized(true);
096                    setDeletionSystemEventStagedModelTypes(
097                            new StagedModelType(DDMStructure.class, JournalArticle.class),
098                            new StagedModelType(DDMTemplate.class, DDMStructure.class),
099                            new StagedModelType(JournalArticle.class),
100                            new StagedModelType(JournalArticle.class, DDMStructure.class),
101                            new StagedModelType(JournalFeed.class),
102                            new StagedModelType(JournalFolder.class));
103                    setExportControls(
104                            new PortletDataHandlerBoolean(
105                                    NAMESPACE, "web-content", true, false,
106                                    new PortletDataHandlerControl[] {
107                                            new PortletDataHandlerBoolean(
108                                                    NAMESPACE, "referenced-content"),
109                                            new PortletDataHandlerBoolean(
110                                                    NAMESPACE, "version-history",
111                                                    PropsValues.JOURNAL_PUBLISH_VERSION_HISTORY_BY_DEFAULT)
112                                    },
113                                    JournalArticle.class.getName()),
114                            new PortletDataHandlerBoolean(
115                                    NAMESPACE, "structures", true, false, null,
116                                    DDMStructure.class.getName(), JournalArticle.class.getName()),
117                            new PortletDataHandlerBoolean(
118                                    NAMESPACE, "feeds", true, false, null,
119                                    JournalFeed.class.getName()));
120                    setPublishToLiveByDefault(
121                            PropsValues.JOURNAL_PUBLISH_TO_LIVE_BY_DEFAULT);
122            }
123    
124            @Override
125            protected PortletPreferences doDeleteData(
126                            PortletDataContext portletDataContext, String portletId,
127                            PortletPreferences portletPreferences)
128                    throws Exception {
129    
130                    if (portletDataContext.addPrimaryKey(
131                                    JournalPortletDataHandler.class, "deleteData")) {
132    
133                            return portletPreferences;
134                    }
135    
136                    JournalArticleLocalServiceUtil.deleteArticles(
137                            portletDataContext.getScopeGroupId());
138    
139                    JournalFolderLocalServiceUtil.deleteFolders(
140                            portletDataContext.getGroupId());
141    
142                    DDMTemplateLocalServiceUtil.deleteTemplates(
143                            portletDataContext.getScopeGroupId());
144    
145                    DDMStructureLocalServiceUtil.deleteStructures(
146                            portletDataContext.getScopeGroupId());
147    
148                    return portletPreferences;
149            }
150    
151            @Override
152            protected String doExportData(
153                            final PortletDataContext portletDataContext, String portletId,
154                            PortletPreferences portletPreferences)
155                    throws Exception {
156    
157                    portletDataContext.addPortletPermissions(
158                            JournalPermission.RESOURCE_NAME);
159    
160                    Element rootElement = addExportDataRootElement(portletDataContext);
161    
162                    rootElement.addAttribute(
163                            "group-id", String.valueOf(portletDataContext.getScopeGroupId()));
164    
165                    if (portletDataContext.getBooleanParameter(NAMESPACE, "feeds")) {
166                            ActionableDynamicQuery feedActionableDynamicQuery =
167                                    new JournalFeedExportActionableDynamicQuery(portletDataContext);
168    
169                            feedActionableDynamicQuery.performActions();
170                    }
171    
172                    if (portletDataContext.getBooleanParameter(NAMESPACE, "structures")) {
173                            List<DDMTemplate> ddmTemplates = new ArrayList<DDMTemplate>();
174    
175                            ActionableDynamicQuery ddmStructureActionableDynamicQuery =
176                                    getDDMStructureActionableDynamicQuery(
177                                            portletDataContext, ddmTemplates, true);
178    
179                            ddmStructureActionableDynamicQuery.performActions();
180    
181                            // Export templates that belong to structures
182    
183                            for (DDMTemplate ddmTemplate : ddmTemplates) {
184                                    StagedModelDataHandlerUtil.exportStagedModel(
185                                            portletDataContext, ddmTemplate);
186                            }
187    
188                            // Export templates that do not belong to structures
189    
190                            ActionableDynamicQuery ddmTemplateActionableDynamicQuery =
191                                    getDDMTemplateActionableDynamicQuery(portletDataContext);
192    
193                            ddmTemplateActionableDynamicQuery.performActions();
194    
195                            // Export DDM structure default values
196    
197                            ActionableDynamicQuery
198                                    ddmStructureDefaultValuesActionableDynamicQuery =
199                                            getDDMStructureDefaultValuesActionableDynamicQuery(
200                                                    portletDataContext);
201    
202                            ddmStructureDefaultValuesActionableDynamicQuery.performActions();
203                    }
204    
205                    if (portletDataContext.getBooleanParameter(NAMESPACE, "web-content")) {
206                            ActionableDynamicQuery folderActionableDynamicQuery =
207                                    new JournalFolderExportActionableDynamicQuery(
208                                            portletDataContext);
209    
210                            folderActionableDynamicQuery.performActions();
211    
212                            ActionableDynamicQuery articleActionableDynamicQuery =
213                                    getArticleActionableDynamicQuery(portletDataContext);
214    
215                            articleActionableDynamicQuery.performActions();
216                    }
217    
218                    return getExportDataRootElementString(rootElement);
219            }
220    
221            @Override
222            protected PortletPreferences doImportData(
223                            PortletDataContext portletDataContext, String portletId,
224                            PortletPreferences portletPreferences, String data)
225                    throws Exception {
226    
227                    portletDataContext.importPortletPermissions(
228                            JournalPermission.RESOURCE_NAME);
229    
230                    if (portletDataContext.getBooleanParameter(NAMESPACE, "feeds")) {
231                            Element feedsElement = portletDataContext.getImportDataGroupElement(
232                                    JournalFeed.class);
233    
234                            List<Element> feedElements = feedsElement.elements();
235    
236                            for (Element feedElement : feedElements) {
237                                    StagedModelDataHandlerUtil.importStagedModel(
238                                            portletDataContext, feedElement);
239                            }
240                    }
241    
242                    Element articlesElement = portletDataContext.getImportDataGroupElement(
243                            JournalArticle.class);
244    
245                    List<Element> articleElements = articlesElement.elements();
246    
247                    if (portletDataContext.getBooleanParameter(NAMESPACE, "structures")) {
248                            Element ddmStructuresElement =
249                                    portletDataContext.getImportDataGroupElement(
250                                            DDMStructure.class);
251    
252                            List<Element> ddmStructureElements =
253                                    ddmStructuresElement.elements();
254    
255                            for (Element ddmStructureElement : ddmStructureElements) {
256                                    StagedModelDataHandlerUtil.importStagedModel(
257                                            portletDataContext, ddmStructureElement);
258                            }
259    
260                            // Import DDM templates that belong to DDM structures
261    
262                            Element ddmTemplatesElement =
263                                    portletDataContext.getImportDataGroupElement(DDMTemplate.class);
264    
265                            List<Element> ddmTemplateElements = ddmTemplatesElement.elements();
266    
267                            for (Element ddmTemplateElement : ddmTemplateElements) {
268                                    StagedModelDataHandlerUtil.importStagedModel(
269                                            portletDataContext, ddmTemplateElement);
270                            }
271    
272                            // Importing DDM structure default values
273    
274                            for (Element articleElement : articleElements) {
275                                    String className = articleElement.attributeValue("class-name");
276    
277                                    if (Validator.isNotNull(className) &&
278                                            className.equals(DDMStructure.class.getName())) {
279    
280                                            StagedModelDataHandlerUtil.importStagedModel(
281                                                    portletDataContext, articleElement);
282                                    }
283                            }
284                    }
285    
286                    if (!portletDataContext.getBooleanParameter(NAMESPACE, "web-content")) {
287                            return portletPreferences;
288                    }
289    
290                    Element foldersElement = portletDataContext.getImportDataGroupElement(
291                            JournalFolder.class);
292    
293                    List<Element> folderElements = foldersElement.elements();
294    
295                    for (Element folderElement : folderElements) {
296                            StagedModelDataHandlerUtil.importStagedModel(
297                                    portletDataContext, folderElement);
298                    }
299    
300                    for (Element articleElement : articleElements) {
301                            StagedModelDataHandlerUtil.importStagedModel(
302                                    portletDataContext, articleElement);
303                    }
304    
305                    return portletPreferences;
306            }
307    
308            @Override
309            protected void doPrepareManifestSummary(
310                            PortletDataContext portletDataContext,
311                            PortletPreferences portletPreferences)
312                    throws Exception {
313    
314                    ActionableDynamicQuery articleActionableDynamicQuery =
315                            getArticleActionableDynamicQuery(portletDataContext);
316    
317                    articleActionableDynamicQuery.performCount();
318    
319                    List<DDMTemplate> ddmTemplates = new ArrayList<DDMTemplate>();
320    
321                    ActionableDynamicQuery ddmStructureActionableDynamicQuery =
322                            getDDMStructureActionableDynamicQuery(
323                                    portletDataContext, ddmTemplates, false);
324    
325                    ddmStructureActionableDynamicQuery.performActions();
326    
327                    ddmStructureActionableDynamicQuery.performCount();
328    
329                    ManifestSummary manifestSummary =
330                            portletDataContext.getManifestSummary();
331    
332                    ActionableDynamicQuery ddmTemplateActionableDynamicQuery =
333                            getDDMTemplateActionableDynamicQuery(portletDataContext);
334    
335                    manifestSummary.addModelAdditionCount(
336                            new StagedModelType(DDMTemplate.class, DDMStructure.class),
337                            ddmTemplateActionableDynamicQuery.performCount() +
338                                    ddmTemplates.size());
339    
340                    ActionableDynamicQuery feedActionableDynamicQuery =
341                            new JournalFeedExportActionableDynamicQuery(portletDataContext);
342    
343                    feedActionableDynamicQuery.performCount();
344    
345                    ActionableDynamicQuery folderActionableDynamicQuery =
346                            new JournalFolderExportActionableDynamicQuery(portletDataContext);
347    
348                    folderActionableDynamicQuery.performCount();
349            }
350    
351            protected ActionableDynamicQuery getArticleActionableDynamicQuery(
352                            final PortletDataContext portletDataContext)
353                    throws SystemException {
354    
355                    return new JournalArticleExportActionableDynamicQuery(
356                            portletDataContext) {
357    
358                                    @Override
359                                    public void addCriteria(DynamicQuery dynamicQuery) {
360                                            super.addCriteria(dynamicQuery);
361    
362                                            if (portletDataContext.getBooleanParameter(
363                                                            NAMESPACE, "version-history")) {
364    
365                                                    return;
366                                            }
367    
368                                            DynamicQuery articleVersionDynamicQuery =
369                                                    DynamicQueryFactoryUtil.forClass(
370                                                            JournalArticle.class, "articleVersion",
371                                                            PortalClassLoaderUtil.getClassLoader());
372    
373                                            articleVersionDynamicQuery.setProjection(
374                                                    ProjectionFactoryUtil.alias(
375                                                            ProjectionFactoryUtil.max("articleVersion.version"),
376                                                            "articleVersion.version"));
377    
378                                            // We need to use the "this" default alias to make sure the
379                                            // database engine handles this subquery as a correlated
380                                            // subquery
381    
382                                            articleVersionDynamicQuery.add(
383                                                    RestrictionsFactoryUtil.eqProperty(
384                                                            "this.resourcePrimKey",
385                                                            "articleVersion.resourcePrimKey"));
386    
387                                            Property versionProperty = PropertyFactoryUtil.forName(
388                                                    "version");
389    
390                                            dynamicQuery.add(
391                                                    versionProperty.eq(articleVersionDynamicQuery));
392                                    }
393    
394                    };
395            }
396    
397            protected ActionableDynamicQuery getDDMStructureActionableDynamicQuery(
398                            final PortletDataContext portletDataContext,
399                            final List<DDMTemplate> ddmTemplates, final boolean export)
400                    throws SystemException {
401    
402                    return new DDMStructureExportActionableDynamicQuery(
403                            portletDataContext) {
404    
405                            @Override
406                            protected void addCriteria(DynamicQuery dynamicQuery) {
407                                    super.addCriteria(dynamicQuery);
408    
409                                    Property classNameIdProperty = PropertyFactoryUtil.forName(
410                                            "classNameId");
411    
412                                    long classNameId = PortalUtil.getClassNameId(
413                                            JournalArticle.class);
414    
415                                    dynamicQuery.add(classNameIdProperty.eq(classNameId));
416                            }
417    
418                            @Override
419                            protected StagedModelType getStagedModelType() {
420                                    return new StagedModelType(
421                                            DDMStructure.class.getName(),
422                                            JournalArticle.class.getName());
423                            }
424    
425                            @Override
426                            protected void performAction(Object object) throws PortalException {
427                                    DDMStructure ddmStructure = (DDMStructure)object;
428    
429                                    if (export) {
430                                            StagedModelDataHandlerUtil.exportStagedModel(
431                                                    portletDataContext, ddmStructure);
432                                    }
433    
434                                    try {
435                                            List<DDMTemplate> ddmStructureDDMTemplates =
436                                                    DDMTemplateLocalServiceUtil.getTemplatesByClassPK(
437                                                            ddmStructure.getGroupId(),
438                                                            ddmStructure.getStructureId());
439    
440                                            ddmTemplates.addAll(ddmStructureDDMTemplates);
441                                    }
442                                    catch (SystemException se) {
443                                    }
444                            }
445    
446                    };
447            }
448    
449            protected ActionableDynamicQuery
450                    getDDMStructureDefaultValuesActionableDynamicQuery(
451                                    final PortletDataContext portletDataContext)
452                            throws SystemException {
453    
454                    return new JournalArticleExportActionableDynamicQuery(
455                            portletDataContext) {
456    
457                            @Override
458                            protected StagedModelType getStagedModelType() {
459                                    return new StagedModelType(
460                                            JournalArticle.class.getName(),
461                                            DDMStructure.class.getName());
462                            }
463    
464                    };
465            }
466    
467            protected ActionableDynamicQuery getDDMTemplateActionableDynamicQuery(
468                            final PortletDataContext portletDataContext)
469                    throws SystemException {
470    
471                    return new DDMTemplateExportActionableDynamicQuery(
472                            portletDataContext) {
473    
474                            @Override
475                            protected void addCriteria(DynamicQuery dynamicQuery) {
476                                    super.addCriteria(dynamicQuery);
477    
478                                    Property classNameIdProperty = PropertyFactoryUtil.forName(
479                                            "classNameId");
480    
481                                    long classNameId = PortalUtil.getClassNameId(
482                                            DDMStructure.class);
483    
484                                    dynamicQuery.add(classNameIdProperty.eq(classNameId));
485    
486                                    Property classPKProperty = PropertyFactoryUtil.forName(
487                                            "classPK");
488    
489                                    dynamicQuery.add(classPKProperty.eq(-1L));
490                            }
491    
492                            @Override
493                            protected StagedModelType getStagedModelType() {
494                                    return new StagedModelType(
495                                            DDMTemplate.class.getName(), DDMStructure.class.getName());
496                            }
497    
498                    };
499            }
500    
501    }